package mindwave.theoracle;


// MindWaver.java
// Andrew Davison, October 2012, ad@fivedots.coe.psu.ac.th

/* Connect to the MindWave and display its Attention, Meditation,
   and BlinkStrength values on a JFreeChart which updates roughly every
   second.

   The Attention and Meditation values are displayed as two line charts,
   while the Blink Strength is shown as bars. All the values can range
   between 0-100, which means that the blink strength is scaled from the
   range 0-255.

   JFReeChart is available at http://www.jfree.org/jfreechart/

   The MindWave code is located in a separate MindReader class, which is
   closely based on the ReadMindWave example. MindReader is threaded, and will
   close its connection to the MindWave when this application's close box is
   clicked.
*/


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;

import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.labels.*;
import org.jfree.chart.plot.*;
import org.jfree.data.xy.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.*;




public class MindWaver extends JFrame 
{
  private static final int X_RANGE = 30;   
     // a spread of 20 seconds are visible on the JFreeChart graph

  private XYSeries attnSeries, mediSeries, blickSeries, rawSeries;
     // JFreeChart data sets for Attention, Meditation, BlinkStrength and the raw Signal
  private MindReader mwReader;



  public MindWaver()
  {
    super("MindWave Oracle Visualization System");

    // initialize 3 series (for 2 line and 1 bar charts)
    attnSeries = new XYSeries("Attention");   // 2 line charts
    mediSeries = new XYSeries("Meditation");
    rawSeries = new XYSeries("Raw Signal");
    
    
    XYSeriesCollection linesData = new XYSeriesCollection();
    linesData.addSeries(attnSeries);
    linesData.addSeries(mediSeries);
    linesData.addSeries(rawSeries);
    
    
    blickSeries = new XYSeries("Blink Strength");   // a bar chart
    // blickSeries.add(X_RANGE, null); 
            // hack to start dynamic addition at left edge of graph
    XYSeriesCollection barData = new XYSeriesCollection();
    barData.addSeries(blickSeries);

    JFreeChart chart = createCombinedChart(linesData, barData);
    ChartPanel chartPanel = new ChartPanel(chart);
	Container c = getContentPane();
	c.add(chartPanel);

    mwReader = new MindReader(attnSeries, mediSeries, blickSeries,rawSeries);
        /* start reading from the MindWave, updating the three chart
           data sets */

    addWindowListener( new WindowAdapter() {
      public void windowClosing(WindowEvent e)
      { mwReader.closeDown(); }    // the MIndWave connection is closed down
    });

    pack();  
    setLocationRelativeTo(null);  // center the window 
    setVisible(true);
   }  // end of MindWaver()



  private JFreeChart createCombinedChart(XYSeriesCollection linesData,
                                         XYSeriesCollection barData) 
  /* the chart is a combination of a line chart (with 2 lines) and a 
     bar chart */
  {
    // create xy line plot renderer
    XYItemRenderer linesRenderer = new StandardXYItemRenderer();
    linesRenderer.setBaseToolTipGenerator(
        new StandardXYToolTipGenerator(
            StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
            new DecimalFormat("0.00"), new DecimalFormat("0.00")
        )
    );
    linesRenderer.setSeriesStroke(0, new BasicStroke(3.0f));   // thicker lines
    linesRenderer.setSeriesStroke(1, new BasicStroke(3.0f));

    // create axes for the plot (same for all data)
    NumberAxis domainAxis = new NumberAxis("Time");
    domainAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
    domainAxis.setAutoRange(true);
    domainAxis.setFixedAutoRange(X_RANGE);  // seconds
    // domainAxis.setLowerMargin(0);

    NumberAxis rangeAxis = new NumberAxis("Value");
    rangeAxis.setRange(-500.0, 500.0);

    // start building the plot with the lines data
    XYPlot plot = new XYPlot(linesData, domainAxis, rangeAxis, linesRenderer);
    
    // customize the plot
    plot.setBackgroundPaint(Color.lightGray);
    plot.setDomainGridlinePaint(Color.white);
    plot.setRangeGridlinePaint(Color.white);
    plot.getRenderer().setSeriesPaint(2, Color.BLACK);

    // create bar chart renderer
    XYItemRenderer barRenderer = new XYBarRenderer(0.8);   // thin bars
    barRenderer.setBaseToolTipGenerator(
        new StandardXYToolTipGenerator(
            StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
            new DecimalFormat("0.00"), new DecimalFormat("0.00")
        )
    );

    // add bar chart data and renderer to the plot
    plot.setDataset(1, barData);
    plot.setRenderer(1, barRenderer);
    
    // return a chart containing the overlaid plot...
    return new JFreeChart("MindWave Output", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
  }  // end of createCombinedChart()


   // ---------------------------------------------------

   public static void main(String args[])
   {  new MindWaver(); }

} // end of MindWaver

